package com.insigma.business.qrcode.soldier.util;

import com.insigma.business.qrcode.soldier.service.impl.SequenceAdapterImpl;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class OkHttp3Util {

    private static final Logger LOGGER = LoggerFactory.getLogger(SequenceAdapterImpl.class);
    private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType MEDIA_TYPE_TEXT_PLAIN = MediaType.parse("text/plain; charset=utf-8");

    private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");

    private static Integer connectTimeout_time = 5;
    private static Integer writeTimeout_time = 5;
    private static Integer readTimeout_time = 5;

    private static OkHttpClient mClient;

    private static OkHttpClient nnsafeOkHttpClient;

    static {
        try {
            mClient = new OkHttpClient.Builder()
                    .connectTimeout(connectTimeout_time, TimeUnit.SECONDS)
                    .writeTimeout(writeTimeout_time, TimeUnit.SECONDS)
                    .readTimeout(readTimeout_time, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .build();

            nnsafeOkHttpClient = getUnsafeOkHttpClient();
        } catch (Exception e) {
            LOGGER.error("{}", e);
        }
    }


    public static String sendByGetUrl(String url) {
        String result;
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = null;
        try {
            response = mClient.newCall(request).execute();
            assert response.body() != null;
            result = response.body().string();
            return result;
        } catch (IOException e) {

        }
        return null;
    }


    public static byte[] sendByGetUrlWithCookies(String url, String cookie) {
        String result;
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Cookie", cookie)
                .build();
        Response response = null;
        try {
            response = getUnsafeOkHttpClient().newCall(request).execute();
            assert response.body() != null;
            return response.body().bytes();
        } catch (IOException e) {

        }
        return null;
    }

    public static String sendByGetUrlWithHeader(String url, Map<String, String> header) {
        String result;
        Request.Builder builder = new Request.Builder()
                .url(url);
        for (Map.Entry<String, String> entry : header.entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue());
        }
        Request request = builder
                .build();
        Response response = null;
        try {
            response = getUnsafeOkHttpClient().newCall(request).execute();
            assert response.body() != null;
            return response.body().string();
        } catch (IOException e) {

        }
        return null;
    }


    public static Response sendByGetUrlWithCookies2(String url, String cookie) {
        String result;
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Cookie", cookie)
                .build();
        Response response = null;
        try {
            response = getUnsafeOkHttpClient().newCall(request).execute();
            return response;
        } catch (IOException e) {

        }
        return null;
    }

    public static String sendByUnsafeGetUrl(String url) {
        String result;
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = null;
        try {
            response = getUnsafeOkHttpClient().newCall(request).execute();
            assert response.body() != null;
            result = response.body().string();

            return result;
        } catch (IOException e) {

        }
        return null;
    }


    public static String sendByPostJson(String url, String json) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON,json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = null;
        try {
            response = mClient.newCall(request).execute();
            String string = response.body().string();

            return string;
        } catch (IOException e) {

        }
        return null;
    }

    public static String sendByPostJsonUnSafe(String url, String json, Map<String, String> header) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request.Builder builder = new Request.Builder()
                .url(url)
                .post(body);
        for (Map.Entry<String, String> entry : header.entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue());
        }

        Request request = builder
                .build();
        Response response = null;
        try {
            response = getUnsafeOkHttpClient().newCall(request).execute();
            String string = response.body().string();

            return string;
        } catch (IOException e) {

        }
        return null;
    }


    public static String sendByPostJson(String url, String json, Map<String, String> header) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request.Builder builder = new Request.Builder()
                .url(url)
                .post(body);
        for (Map.Entry<String, String> entry : header.entrySet()) {
            builder.addHeader(entry.getKey(), entry.getValue());
        }

        Request request = builder
                .build();
        Response response = null;
        try {
            response = mClient.newCall(request).execute();
            String string = response.body().string();

            return string;
        } catch (IOException e) {

        }
        return null;
    }


    public static String sendByPostJsonOfUnsafeAndRepeat(String url, String json) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = null;
        for (int i = 0; i < 30 && response == null; i++) {
            try {
                response = nnsafeOkHttpClient.newCall(request).execute();
                String string = response.body().string();

                return string;
            } catch (IOException e) {

            }
        }

        return null;
    }


    public static String sendByPostText(String url, String text, Map<String, String> header) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_TEXT_PLAIN, text);
        Request.Builder postBuilder = new Request.Builder().url(url).post(body);
        if (header != null) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                postBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }

        Request request = postBuilder
                .build();
        Response response = null;
        try {
            response = mClient.newCall(request).execute();
            String string = response.body().string();

            return string;
        } catch (IOException e) {

        }
        return null;
    }


    public static Response responseByPostJson(String url, String json) {
        RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = null;
        try {
            response = mClient.newCall(request).execute();
            return response;
        } catch (IOException e) {

        }
        return null;
    }

    public static String upload(String url, String filePath, String fileName) {
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", fileName,
                        RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
                .build();

        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        try {
            Response response = getUnsafeOkHttpClient().newCall(request).execute();
            return response.body().string();
        } catch (IOException e) {

            return null;
        }
    }

    public static String sendFormData(String uri, Map<String, String> requestMap, Map<String, String> headersMap) {
        // 构建表单请求体
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        for (Map.Entry<String, String> entry : requestMap.entrySet()) {
            formBodyBuilder.add(entry.getKey(), entry.getValue());
        }
        RequestBody requestBody = formBodyBuilder.build();

        // 构建请求对象并添加请求头
        Request.Builder requestBuilder = new Request.Builder()
                .url(uri)
                .post(requestBody);

        if (headersMap != null) {
            for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }


        Request request = requestBuilder.build();

        try {
            Response response = mClient.newCall(request).execute();
            String jsonString = response.body().string();

            return jsonString;

        } catch (Exception e) {

        }
        return null;
    }


    public static String sendWwwFormData(String uri, Map<String, String> requestMap) {
        FormBody.Builder builder = new FormBody.Builder();
        for (String s : requestMap.keySet()) {
            builder.addEncoded(s, requestMap.get(s));
        }
        Request request = new Request.Builder()
                .url(uri)
                .post(builder.build())
                .build();
        try {
            Response response = mClient.newCall(request).execute();
            String jsonString = response.body().string();

            return jsonString;

        } catch (Exception e) {

        }
        return null;
    }


    public static String sendXml(String uri, String xml) {
        RequestBody body = RequestBody.create(MediaType.parse("application/xml"), xml);
        Request request = new Request.Builder()
                .url(uri)
                .post(body)
                .build();

        try {
            Response response = mClient.newCall(request).execute();
            String jsonString = response.body().string();

            return jsonString;

        } catch (Exception e) {

        }
        return null;
    }

    public static OkHttpClient buildBasicAuthClient(final String name, final String password) {
        return new OkHttpClient.Builder().authenticator(new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) throws IOException {
                String credential = Credentials.basic(name, password);
                return response.request().newBuilder().header("Authorization", credential).build();
            }
        }).build();
    }


    public static String sendMultiFile(String uri, String path, String name) {
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", name,
                        RequestBody.create(MediaType.parse("multipart/form-data"), new File(path)))
                .build();

        Request request = new Request.Builder()
                .url(uri)
                .post(requestBody)
                .build();

        try {
            Response response = mClient.newCall(request).execute();
            String jsonString = response.body().string();

            return jsonString;

        } catch (Exception e) {

        }
        return null;
    }


    private static OkHttpClient getUnsafeOkHttpClient() {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .connectTimeout(3, TimeUnit.MINUTES)
                    .writeTimeout(1, TimeUnit.MINUTES)
                    .readTimeout(1, TimeUnit.MINUTES)
                    .sslSocketFactory(SSLSocketClient.getSSLSocketFactory(),SSLSocketClient.getX509TrustManager())
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            return true;
                        }
                    });

            OkHttpClient okHttpClient = builder.build();
            return okHttpClient;
        } catch (Exception e) {

            throw new RuntimeException(e);
        }
    }


    public static String sendByPostMap(String url, Map<String, String> params, Map<String, String> header) {
        String result;
        StringBuilder content = new StringBuilder();
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            content.append(entry.getKey()).append("=").append(entry.getValue());
            if (iterator.hasNext()) {
                content.append("&");
            }
        }

        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_TEXT, content.toString());
        Request.Builder requestBuilder = new Request.Builder().url(url).post(requestBody);
        if (header != null) {
            for (String key : header.keySet()) {
                requestBuilder.addHeader(key, header.get(key));
            }
        }

        Request request = requestBuilder.build();
        Response response = null;
        try {
            response = nnsafeOkHttpClient.newCall(request).execute();
            result = response.body().string();

            return result;
        } catch (IOException e) {

        }
        return null;
    }

    public static String sendByPostMap(String url, String content, Map<String, String> header) {
        String result;

        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_TEXT, content);
        Request.Builder requestBuilder = new Request.Builder().url(url).post(requestBody);
        if (header != null) {
            for (String key : header.keySet()) {
                requestBuilder.addHeader(key, header.get(key));
            }
        }

        Request request = requestBuilder.build();
        Response response = null;
        try {
            response = nnsafeOkHttpClient.newCall(request).execute();
            result = response.body().string();

            return result;
        } catch (IOException e) {

        }
        return null;
    }


    public static String sendByPostMap(String url, Map<String, String> params) {
        String result;
        OkHttpClient client = new OkHttpClient();
        StringBuilder content = new StringBuilder();
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            content.append(entry.getKey()).append("=").append(entry.getValue());
            if (iterator.hasNext()) {
                content.append("&");
            }
        }

        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_TEXT, content.toString());
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
            assert response.body() != null;
            result = response.body().string();

            return result;
        } catch (IOException e) {

        }
        return null;
    }

}
